﻿/**
 * Licensed to Open-Ones Group under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Open-Ones Group licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
namespace IPresenter
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Windows.Forms;
    using Microsoft.Office.Core;
    using Microsoft.Office.Interop.PowerPoint;
   
    /// <summary>
    /// This class provides functions to work with Powerpoint
    /// </summary>
    public class PowerPointSupport
    {
        /// <summary>
        /// Presentation is fullscreen or normal
        /// </summary>
        private static bool FullScreenNot;

        /// <summary>
        /// List of file powerpoint which are running in PC.
        /// </summary>
        private static List<string> LFPowerPoint;

        /// <summary>
        /// Object ApplicationClass
        /// </summary>
        private static ApplicationClass ManagerApplication = new ApplicationClass();

        /// <summary>
        /// Contain object presenation which is being shown full screen mode
        /// </summary>
        private static Presentation ShowingPresentation;

        /// <summary>
        /// Slide number which user would like to go
        /// </summary>
        private static int SlideNumberGoTo;

        /// <summary>
        /// Contain presentation which is being shown in normal mode
        /// </summary>
        private static DocumentWindow Window;

        /// <summary>
        /// Name of file powerpoint is being controlled
        /// </summary>
        private static string PowerPointFileName;

        /// <summary>
        /// Update list of file powerpoint
        /// </summary>
        private static UpdateFileEventHandler UpdateFileEvent;

        /// <summary>
        /// Update list of file powerpoint
        /// </summary>
        public delegate void UpdateFileEventHandler();

        /// <summary>
        /// Gets or sets list file powerpoint are being opened.
        /// </summary>
        public static List<string> ListFilePowerPoint
        {
            get { return PowerPointSupport.LFPowerPoint; }
            set { PowerPointSupport.LFPowerPoint = value; }
        } 
       
        /// <summary>
        /// Gets or sets event update file when a file power is opened or closed
        /// </summary>
        public static UpdateFileEventHandler UpdateFile
        {
            get { return PowerPointSupport.UpdateFileEvent; }
            set { PowerPointSupport.UpdateFileEvent = value; }
        }

        /// <summary>
        /// Gets or sets slide number which you would like to go.
        /// </summary>
        public static int SlideNumber
        {
            get { return PowerPointSupport.SlideNumberGoTo; }
            set { PowerPointSupport.SlideNumberGoTo = value; }
        }

        /// <summary>
        /// Gets or sets powerpoint file name is being controlled
        /// </summary>
        public static string FileName
        {
            get { return PowerPointSupport.PowerPointFileName; }
            set { PowerPointSupport.PowerPointFileName = value; }
        }

        /// <summary>
        /// Init event
        /// </summary>
        public static void InitEvent()
        {
            ManagerApplication.SlideShowBegin += new EApplication_SlideShowBeginEventHandler(appl_SlideShowBegin);
            ManagerApplication.SlideShowEnd += new EApplication_SlideShowEndEventHandler(appl_SlideShowEnd);
            ManagerApplication.PresentationOpen += new EApplication_PresentationOpenEventHandler(appl_PresentationOpen);
            ManagerApplication.PresentationClose += new EApplication_PresentationCloseEventHandler(appl_PresentationClose);
        }

        /// <summary>
        /// When file powerpoint is being closed
        /// </summary>
        /// <param name="Pres">Presentation caused event</param>
        public static void appl_PresentationClose(Presentation Pres)
        {
            GetListOfFilePowerPoint();
            UpdateFileEvent();
        }

        /// <summary>
        /// When file powerpoint is being opened 
        /// </summary>
        /// <param name="Pres">Presentation cause event</param>
        public static void appl_PresentationOpen(Presentation Pres)
        {
            UpdateFileEvent();
            GetListOfFilePowerPoint();
        }

        /// <summary>
        /// When slide show window end
        /// </summary>
        /// <param name="Pres">Presentation caused event</param>
        public static void appl_SlideShowEnd(Presentation Pres)
        {
            FullScreenNot = false;
            GetListOfFilePowerPoint();
        }

        /// <summary>
        /// When slide show window begin
        /// </summary>
        /// <param name="Wn">Slide Show Window</param>
        public static void appl_SlideShowBegin(SlideShowWindow Wn)
        {
            FullScreenNot = true;
            ShowingPresentation = Wn.Presentation;
            GetListOfFilePowerPoint();
        }

        /// <summary>
        /// Determine whether presentation is fullscreen or normal 
        /// </summary>
        /// <returns>
        /// true: if presentation is fullscreen
        /// false: contrary
        /// </returns>
        public static bool IsFullScreen()
        {
           int intHWnd = ApiFunction.GetForegroundWindow();
           foreach (SlideShowWindow ssw in ManagerApplication.SlideShowWindows)
           {
               if (ssw.HWND == intHWnd)
               {
                   ShowingPresentation = ssw.Presentation;
                   ssw.Activate();
                   return true;
               }
           }

           foreach (DocumentWindow dw in ManagerApplication.Windows)
           {
               if (dw.HWND == intHWnd)
               {
                   Window = dw;
                   Window.Activate();
                   break;
               }
           }

           return false;
        }

        /// <summary>
        /// Execute next slide
        /// </summary>
        public static void NextSlide()
        {
            if (FullScreenNot == true)
            {
                try
                {
                    ShowingPresentation.SlideShowWindow.View.Next();
                }
                catch (COMException com)
                {
                    Logs.WriteErrorMessage(com.Message);
                }
            }
            else
            {
                try
                {
                    Slide sl = (Slide)Window.View.Slide;
                    Window.View.GotoSlide(sl.SlideNumber + 1);
                }
                catch (Exception ex)
                {
                    Logs.WriteErrorMessage(ex.Message);
                }
            }
        }

        /// <summary>
        /// Execute previous slide
        /// </summary>
        public static void PreviousSlide()
        {
            if (FullScreenNot == true)
            {
                try
                {
                    ShowingPresentation.SlideShowWindow.View.Previous();
                }
                catch (COMException com)
                {
                    Logs.WriteErrorMessage(com.Message);
                }
            }
            else
            {
                try
                {
                    Slide sl = (Slide)Window.View.Slide;
                    Window.View.GotoSlide(sl.SlideNumber - 1);
                }
                catch (Exception ex)
                {
                    Logs.WriteErrorMessage(ex.Message);
                }
            }
        }

        /// <summary>
        /// Execute go to slide
        /// </summary>
        /// <param name="slideNumber">Slide number which user would like go to</param>
        /// <returns>
        /// true: success
        /// false: fail
        /// </returns>
        public static bool GoToSlide(int slideNumber)
        {
            if (FullScreenNot == true)
            {
                try
                {
                    ShowingPresentation.SlideShowWindow.View.GotoSlide(slideNumber, MsoTriState.msoTrue);
                }
                catch (COMException com)
                {
                    Logs.WriteErrorMessage(com.Message);
                    return false;
                }
            }
            else
            {
                try
                {
                    Window.View.GotoSlide(slideNumber);
                }
                catch (Exception ex)
                {
                    Logs.WriteErrorMessage(ex.Message);
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// Execute full screen
        /// </summary>
        public static void FullScreen()
        {
            if (FullScreenNot == false)
            {
                Window.Presentation.SlideShowSettings.Run();
            }
        }

        /// <summary>
        /// Get list of file powerpoint which are being opened in PC
        /// </summary>
        /// <returns>Danh sách các file được mở bằng powerpoint</returns>
        public static List<string> GetListOfFilePowerPoint()
        {
            ListFilePowerPoint = new List<string>();
            foreach (DocumentWindow win in ManagerApplication.Windows)
            {
                ListFilePowerPoint.Add(win.Presentation.Name);
            }

            return ListFilePowerPoint;
        }

        /// <summary>
        /// Determine presentation which is being controlled
        /// </summary>
        /// <param name="fileName">Name of file powerpoint</param>
        /// <returns>
        /// true: if file powerpoint exist
        /// false: if file powerpoint doesn't exist
        /// </returns>
        public static bool DetermineWindowOrPresentation(string fileName)
        {
            foreach (SlideShowWindow sl in ManagerApplication.SlideShowWindows)
            {
                if (sl.Presentation.Name == fileName)
                {
                    FullScreenNot = true;
                    ShowingPresentation = sl.Presentation;
                    sl.Activate();
                    return true;
                }
            }

            foreach (DocumentWindow dwWin in ManagerApplication.Windows)
            {
                if (dwWin.Presentation.Name == fileName)
                {
                    FullScreenNot = false;
                    Window = dwWin;
                    Window.Activate();
                    return true;
                }
            }

            return false;
        }
        
        /// <summary>
        /// Determine presentation which is being activated
        /// </summary>
        /// <returns>
        /// true: if presentation exist
        /// false: if presentation doesn't exist
        /// </returns>
        public static bool DetermineWindowOrPresentation()
        {
            int intSizeClassName = 0;
            int intHWnd = ApiFunction.GetForegroundWindow();
            StringBuilder strBuilderClassName = new StringBuilder(255);
            intSizeClassName = ApiFunction.GetClassName(intHWnd, strBuilderClassName, 255);
            string className = strBuilderClassName.ToString();
            if (intSizeClassName == 0)
            {
                return false;
            }

            if (className.Equals("screenClass") == true)
            {
                PowerPointSupport.ShowingPresentation = ManagerApplication.ActivePresentation;
                PowerPointSupport.FullScreenNot = true;
                FileName = ShowingPresentation.Name;
                return true;
            }

            if (Regex.IsMatch(className, @"PP([A-Za-z0-9\-]+)FrameClass$") == true)
            {
                PowerPointSupport.Window = ManagerApplication.ActiveWindow;
                PowerPointSupport.FullScreenNot = false;
                FileName = Window.Presentation.Name;
                return true;
            }

            return false;
        }

        /// <summary>
        /// Execute resume full screen
        /// </summary>
        public static void ResumeFullScreen()
        {
            if (FullScreenNot == false)
            {
                try
                {
                    Slide sl = (Slide)Window.View.Slide;
                    Window.Presentation.SlideShowSettings.StartingSlide = sl.SlideNumber;
                    Window.Presentation.SlideShowSettings.EndingSlide = Window.Presentation.Slides.Count;
                    Window.Presentation.SlideShowSettings.RangeType = PpSlideShowRangeType.ppShowSlideRange;
                    Window.Presentation.SlideShowSettings.Run();
                }
                catch (COMException com)
                {
                    Logs.WriteErrorMessage(com.Message);
                }
            }
        }

        /// <summary>
        /// Execute end full screen
        /// </summary>
        public static void EndFullScreen()
        {
            if (FullScreenNot == true)
            {
                ShowingPresentation.SlideShowWindow.View.Exit();
            }
        }

        /// <summary>
        /// Determine whether file presentation is window which is activated
        /// </summary>
        /// <param name="namePresentation">Name of file powerpoint</param>
        /// <param name="captionForegroundWindow">Caption of active window</param>
        /// <returns>
        /// true: if presentation is activated
        /// false: if presentation is not activated
        /// </returns>
        public static bool Contains(string namePresentation, string captionForegroundWindow)
        {
            string extension = ".ppt";
            int intLength = captionForegroundWindow.IndexOf(extension, StringComparison.CurrentCulture);
            for (int i = 0; i < intLength; i++)
            {
                if (namePresentation[i] != captionForegroundWindow[i])
                {
                    return false;
                }
            }

            if (namePresentation.Length == intLength + 4)
            {
                for (int i = intLength; i < intLength + 4; i++)
                {
                    if (namePresentation[i] != captionForegroundWindow[i])
                    {
                        return false;
                    }
                }
            }

            if (namePresentation.Length == intLength + 5)
            {
                for (int i = intLength; i < intLength + 5; i++)
                {
                    if (namePresentation[i] != captionForegroundWindow[i])
                    {
                        return false;
                    }
                }
            }

            return true;
        }
    }
}